package vivace.view;

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.HashSet;
import java.util.Observable;
import java.util.Observer;
import java.util.Vector;

import javax.sound.midi.MidiEvent;
import javax.sound.midi.Track;
import javax.swing.DefaultListCellRenderer;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

import lib.Texter.Text;
import vivace.helper.GUIHelper;
import vivace.helper.ProjectHelper;
import vivace.model.Action;
import vivace.model.App;

public class EventListFrame extends JFrame implements Observer {
	
	private JButton editButton;
	
	private static final long serialVersionUID = -6416385332001932523L;
	JList eventList;

	/**
	 * Constructor
	 */
	public EventListFrame() {
		setTitle(Text.getText("EVENT_LIST") + " - " + App.Project.getTrackName(App.UI.getTrackSelection().iterator().next()));
		setPreferredSize(new Dimension(500, 600));
		setAlwaysOnTop(true);
		setIconImage(GUIHelper.icon);
		
		Controller controller = new Controller();
		
		App.addProjectObserver(this, App.Source.ALL);
		
		/* create UI */
		Container c = getContentPane();
		c.setLayout(new BorderLayout());
		
		eventList = new JList(prepareData());
		eventList.setCellRenderer(new EventListCellRenderer());
		eventList.addListSelectionListener(controller);
		
		c.add(new JLabel("<html>(ME)=Meta message<br>(SH)=Short message<br>(SY)=Sysex message<br>(UN)=Unknown message type</html>"), BorderLayout.NORTH);
		c.add(new JScrollPane(eventList), BorderLayout.CENTER);
		
		JPanel buttonPanel = new JPanel();
		buttonPanel.setAlignmentX(Component.RIGHT_ALIGNMENT);
		
		// edit button
		editButton = new JButton("Edit");
		editButton.setActionCommand("edit");
		editButton.addActionListener(controller);
		editButton.setEnabled(!eventList.isSelectionEmpty());

		buttonPanel.add(editButton);
		
		c.add(buttonPanel, BorderLayout.SOUTH);
		
		pack();
	}
	
	private Vector<MidiEvent> prepareData() {
		int index = App.UI.getTrackSelection().iterator().next();
		Track t = App.Project.getTrack(index);
		
		return ProjectHelper.allMidiEvents(t);
	}

	@Override
	public void update(Observable o, Object arg) {

		Action a = (Action) arg;
		HashSet<Integer> trackSelection = App.UI.getTrackSelection();

		if( App.UI.getTrackSelection().size() == 0){
			eventList.clearSelection();
		} else {
		
			if ((a == Action.NOTE_ADDED || a == Action.NOTE_MOVED
				|| a == Action.NOTE_REMOVED || a == Action.TRACK_SELECTION_CHANGED
				|| a == Action.TIMESIGNATURE_ADDED || a == Action.TIMESIGNATURE_REMOVED || a == Action.TIMESIGNATRUE_EDIT
				|| a == Action.TRACK_PARAMETERS_EDITED) && trackSelection.size() > 0) {
			
					eventList.setListData(prepareData());
					System.out.println("data changed");
			}
			
			if (a == Action.TRACK_SELECTION_CHANGED) {
				setTitle(Text.getText("EVENT_LIST") + " - " + App.Project.getTrackName(App.UI.getTrackSelection().iterator().next()));
			}
		}
	}
	
	private class EventListCellRenderer extends DefaultListCellRenderer {

		private static final long serialVersionUID = 4640795017747592133L;

		@Override
		public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
			JLabel l = (JLabel) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
			l.setText( index + ", " + ProjectHelper.prettyPrint((MidiEvent) value));
			
			return l;
		}
		
	}
	
	private class Controller implements ActionListener, ListSelectionListener {

		@Override
		public void valueChanged(ListSelectionEvent e) {
			if (!e.getValueIsAdjusting()) {
				editButton.setEnabled(!eventList.isSelectionEmpty());
			}
		}

		@Override
		public void actionPerformed(ActionEvent e) {
			String cmd = e.getActionCommand();
			
			if (cmd.equals("edit")) {
				MidiEvent ev = (MidiEvent) eventList.getSelectedValue();
				EventEditFrame eef = new EventEditFrame(ev);
				eef.setVisible(true);
			}
			
		}
		
	}
}
